type User1 = {
  id: number;
  kind: string;
};

function makeCustomer<T extends User1>(u: T): T {
  // Error（TS 编译器版本：v4.4.2）
  // Type '{ id: number; kind: string; }' is not assignable to type 'T'.
  // '{ id: number; kind: string; }' is assignable to the constraint of type 'T', 
  // but 'T' could be instantiated with a different subtype of constraint 'User'.
  // T: 泛型能不能被实例化

  return {
    // ...u,
    id: u.id,
    kind: 'customer'
  } as T
}
// 用ts发布订阅

type FnCallback<T> = (...args: T[]) => void;

interface EventEmitter<T> {
  [key:string] :  Array<FnCallback<T>>
}
class PubSub1<T> {
  private subscribers : EventEmitter<T>
  constructor() {
    // 存起来 : {西瓜 : [function(msg) {console.log(msg)},function(msg) {console.log(msg)},]}
    // 存起来 : {小魔仙 : [function(msg) {console.log(msg)},function(msg) {console.log(msg)},]}
    this.subscribers = {};
  }
  // 订阅
  subscribe(event:string, callback:FnCallback<T>):void { // 123 ()=>{}
    // 如果没有这个事件，那么就创建一个
    if (!this.subscribers[event]) {
      this.subscribers[event] = [];
    }
    this.subscribers[event].push(callback)
  }
  // 发布
  publish(event:string, data:T):void {
    if(!this.subscribers[event]){
      return 
    }
    this.subscribers[event].forEach(callback=>callback(data))
  }
}

let pubsub1 = new PubSub1<{msg:string}>()

pubsub1.subscribe('西瓜', res=>console.log(res.msg))
pubsub1.subscribe('小魔仙', res=>console.log(res.msg))
pubsub1.subscribe('小魔仙', res=>console.log(res.msg))
pubsub1.publish('西瓜', {msg:'西瓜'})

